package com.my.security.security;

import com.my.security.security.handle.MyAccessDeniedHandel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;


@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true) // 开启方法级安全验证
//开启以后--方法上加 @PreAuthorize("hasAnyRole('user')") // 只能user角色才能访问该方法
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MyAccessDeniedHandel myAccessDeniedHandel;
    @Autowired
    private CustomUserDetailsService userDetailsService;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private PersistentTokenRepository persistentTokenRepository;

    @Bean
    public PersistentTokenRepository getPersistentTokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        //第一次启动自动建表,第二次注释掉
        //jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }
    /*指定加密方式*/
    @Bean
    public PasswordEncoder getPw(){
        return new BCryptPasswordEncoder();
    }


//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        auth
//                // 从数据库读取的用户进行身份认证
//                .userDetailsService(userDatailService)
//                .passwordEncoder(passwordEncoder());
//    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .formLogin() //表单提交
//                .usernameParameter("username123")//修改登录参数
//                .passwordParameter("password123")
            //表单提交的登录地址 配置了之后才会走自定义登录逻辑
            .loginProcessingUrl("/login")
            //登录界面
            .loginPage("/login.html")
            //登录成功界面 必须是post请求
            .successForwardUrl("/toMain")
//            .successHandler(new MySuccessHandle("http://wwww.baidu.com"))
            //登录失败跳转 必须是post请求
            .failureForwardUrl("/toError");
//            .failureHandler(new MyFailHandle("/error.html"));
        //配置没有权限访问自定义跳转的页面
//        http.exceptionHandling().accessDeniedPage("/unauth.html");
        http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandel);
        //关闭防火墙--csrf防护
        //post请求要关闭csrf验证,不然访问报错；实际开发中开启，需要前端配合传递其他参数
        //前端 _csrf参数的token  _csrf.token
        //csrf跨站请求伪造
        http.csrf().disable();
        //授权认证
        http.authorizeRequests()
                //不需要认证-放行
//                .antMatchers(HttpMethod.POST, "/add-user").permitAll() // 允许post请求/add-user，而无需认证
                .antMatchers("/error.html").permitAll()
//                .antMatchers("/error.html").access("permitAll()")
                .antMatchers("/login.html").permitAll()
                //拥有admin权限才能访问
//                .antMatchers("/main1.html").hasAuthority("admin")
//                .antMatchers("/main1.html").hasAnyAuthority("12","12")
//                .antMatchers("/main1.html").hasRole("abc")
//                .antMatchers("/main1.html").access("hasRole(\"abc\")")
//                .antMatchers("/main1.html").hasAnyRole("abc","abc1")
//                .antMatchers("/main1.html").hasIpAddress("127.0.0.1")
//                .antMatchers("**/css/**","**/js/**","**/*.png").permitAll()
//                .regexMatchers(".+[.]png").permitAll()//正则表达式匹配
//                .mvcMatchers("/demo").servletPath("/xxx").permitAll()//servlet.path的匹配
                //所有请求都必须认证-登录之后访问
                .anyRequest().authenticated();
                //根据url判断权限
//                .anyRequest().access("@myServiceImpl.hasPermission(request,authentication)");
        //不能在调父级了
//        super.configure(http);
        //默认失效时间是2周
        http.rememberMe()
                //定义失效时间 秒
                .tokenValiditySeconds(60)
                //参数
//                .rememberMeParameter("")
                //登录逻辑
                .userDetailsService(userDetailsService)
                //持久层对象
                .tokenRepository(persistentTokenRepository);

        http.logout()
//                .addLogoutHandler()
                //默认logout
//                .logoutUrl("")
                //默认 /login?logout
                .logoutSuccessUrl("/login.html");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }


}
